<?php

namespace addons\aliyunemail\library\sdk;

/**
 * 阿里云邮件推送服务客户端
 */
class Client
{
    private $accessKeyId;
    private $accessKeySecret;
    private $endpoint;
    private $apiVersion = '2015-11-23';
    private $signatureMethod = 'HMAC-SHA1';
    private $signatureVersion = '1.0';

    public function __construct($accessKeyId, $accessKeySecret, $endpoint = 'dm.aliyuncs.com')
    {
        $this->accessKeyId = $accessKeyId;
        $this->accessKeySecret = $accessKeySecret;
        $this->endpoint = $endpoint;
    }

    /**
     * 发送邮件
     * @param string $toAddress 收件人邮箱
     * @param string $fromAlias 发信地址别名
     * @param string $fromAddress 发信地址
     * @param string $subject 邮件主题
     * @param string $htmlBody HTML邮件内容
     * @param string $textBody 纯文本邮件内容
     * @return array
     */
    public function sendMail($toAddress, $fromAlias, $fromAddress, $subject, $htmlBody = '', $textBody = '')
    {
        $params = [
            'Action' => 'SingleSendMail',
            'Version' => $this->apiVersion,
            'RegionId' => 'cn-hangzhou',
            'ToAddress' => $toAddress,
            'FromAlias' => $fromAlias,
            'FromAddress' => $fromAddress,
            'Subject' => $subject,
            'AccessKeyId' => $this->accessKeyId,
            'Format' => 'JSON',
            'SignatureMethod' => $this->signatureMethod,
            'SignatureVersion' => $this->signatureVersion,
            'SignatureNonce' => uniqid(),
            'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
        ];

        if (!empty($htmlBody)) {
            $params['HtmlBody'] = $htmlBody;
        }
        if (!empty($textBody)) {
            $params['TextBody'] = $textBody;
        }

        // 生成签名
        $params['Signature'] = $this->generateSignature($params);

        // 发送请求
        $url = 'https://' . $this->endpoint . '/';
        $response = $this->httpRequest($url, $params);

        return json_decode($response, true);
    }

    /**
     * 使用模板发送邮件
     * @param string $toAddress 收件人邮箱
     * @param string $fromAlias 发信地址别名
     * @param string $fromAddress 发信地址
     * @param string $templateName 模板名称
     * @param array $templateParam 模板参数
     * @return array
     */
    public function sendTemplateMail($toAddress, $fromAlias, $fromAddress, $templateName, $templateParam = [])
    {
        $params = [
            'Action' => 'SingleSendMail',
            'Version' => $this->apiVersion,
            'RegionId' => 'cn-hangzhou',
            'ToAddress' => $toAddress,
            'FromAlias' => $fromAlias,
            'FromAddress' => $fromAddress,
            'TemplateName' => $templateName,
            'AccessKeyId' => $this->accessKeyId,
            'Format' => 'JSON',
            'SignatureMethod' => $this->signatureMethod,
            'SignatureVersion' => $this->signatureVersion,
            'SignatureNonce' => uniqid(),
            'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
        ];

        if (!empty($templateParam)) {
            $params['TagName'] = json_encode($templateParam);
        }

        // 生成签名
        $params['Signature'] = $this->generateSignature($params);

        // 发送请求
        $url = 'https://' . $this->endpoint . '/';
        $response = $this->httpRequest($url, $params);

        return json_decode($response, true);
    }

    /**
     * 生成签名
     * @param array $params
     * @return string
     */
    private function generateSignature($params)
    {
        // 排序参数
        ksort($params);
        
        // 构建查询字符串
        $queryString = '';
        foreach ($params as $key => $value) {
            $queryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
        }
        $queryString = substr($queryString, 1);

        // 构建签名字符串
        $stringToSign = 'GET&' . $this->percentEncode('/') . '&' . $this->percentEncode($queryString);
        
        // 生成签名
        $signature = base64_encode(hash_hmac('sha1', $stringToSign, $this->accessKeySecret . '&', true));
        
        return $signature;
    }

    /**
     * URL编码
     * @param string $str
     * @return string
     */
    private function percentEncode($str)
    {
        $res = urlencode($str);
        $res = preg_replace('/\+/', '%20', $res);
        $res = preg_replace('/\*/', '%2A', $res);
        $res = preg_replace('/%7E/', '~', $res);
        return $res;
    }

    /**
     * 发送HTTP请求
     * @param string $url
     * @param array $params
     * @return string
     */
    private function httpRequest($url, $params)
    {
        $queryString = http_build_query($params);
        $fullUrl = $url . '?' . $queryString;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $fullUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_USERAGENT, 'aliyun-email-php-sdk');

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new \Exception('CURL Error: ' . $error);
        }

        if ($httpCode !== 200) {
            throw new \Exception('HTTP Error: ' . $httpCode);
        }

        return $response;
    }
}
